/*-
 * Copyright (c) 2013 Shang-Rong Cai. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $ MTBLAS TEST: tst_lv_2_gmv.c    Rev. 0.0.15    2013-11-15T17:40+08:00 $
 */

#include <stdio.h>
#include <complex.h>

#include <cblas.h>

#include <tst_lv_a_com.h>

int test_gemvf(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    float alpha;
    float beta;

    mat_ff_t ma;

    vec_ff_t vx;
    vec_ff_t vy;
    vec_ff_t vz;

    float buf_st;  /* Single-thread return */
    float buf_mt;  /* Multi-threads return */
    float buf_cf;  /* cblas return */

    printf("gemvf() --> cblas_sgemv()\n");
    alpha = random_float();
    beta = -random_float();

    ierr = mat_ff_create(PROPER_MATRIX_MAX, PROPER_MATRIX_MIN, &ma);

    ierr = vec_ff_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_C_SIZE_RUN, &vx);
    ierr = vec_ff_twins_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_R_SIZE_RUN, &vy, &vz);

    /* Row-Major, No Transpose */
    ierr = stblas_gemvf(MTBLAS_ROW_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2f(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_ff_twins_reset(&vy, &vz);

    ierr = mtblas_gemvf(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2f(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_ff_twins_reset(&vy, &vz);

    cblas_sgemv(CblasRowMajor, CblasNoTrans, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    buf_cf = cblas_snrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("ROW_MAJOR, TRANS_NONE:\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    /* Row-Major, Transpose */
    ierr = vec_ff_twins_reset(&vy, &vz);

    ierr = stblas_gemvf(MTBLAS_ROW_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2f(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_ff_twins_reset(&vy, &vz);

    ierr = mtblas_gemvf(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2f(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_ff_twins_reset(&vy, &vz);

    cblas_sgemv(CblasRowMajor, CblasTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    buf_cf = cblas_snrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("ROW_MAJOR, TRANS:\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    /* Row-Major, Conjugate Transpose */
    ierr = vec_ff_twins_reset(&vy, &vz);

    ierr = stblas_gemvf(MTBLAS_ROW_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2f(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_ff_twins_reset(&vy, &vz);

    ierr = mtblas_gemvf(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2f(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_ff_twins_reset(&vy, &vz);

    cblas_sgemv(CblasRowMajor, CblasConjTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    buf_cf = cblas_snrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("ROW_MAJOR, CONJ TRANS:\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    /* Column-Major, No Transpose */
    ierr = vec_ff_twins_reset(&vy, &vz);

    ierr = stblas_gemvf(MTBLAS_COL_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2f(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_ff_twins_reset(&vy, &vz);

    ierr = mtblas_gemvf(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2f(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_ff_twins_reset(&vy, &vz);

    cblas_sgemv(CblasColMajor, CblasNoTrans, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    buf_cf = cblas_snrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("COL_MAJOR, TRANS_NONE:\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    /* Column-Major, Transpose */
    ierr = vec_ff_twins_reset(&vy, &vz);

    ierr = stblas_gemvf(MTBLAS_COL_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2f(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_ff_twins_reset(&vy, &vz);

    ierr = mtblas_gemvf(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2f(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_ff_twins_reset(&vy, &vz);

    cblas_sgemv(CblasColMajor, CblasTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    buf_cf = cblas_snrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("COL_MAJOR, TRANS:\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    /* Column-Major, Conjugate Transpose */
    ierr = vec_ff_twins_reset(&vy, &vz);

    ierr = stblas_gemvf(MTBLAS_COL_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2f(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_ff_twins_reset(&vy, &vz);

    ierr = mtblas_gemvf(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2f(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_ff_twins_reset(&vy, &vz);

    cblas_sgemv(CblasColMajor, CblasConjTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    buf_cf = cblas_snrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("COL_MAJOR, CONJ TRANS:\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    ierr = vec_ff_delete(&vx);
    ierr = vec_ff_delete(&vy);
    ierr = vec_ff_delete(&vz);

    ierr = mat_ff_delete(&ma);

    return ierr;
}


int test_gemv(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    double alpha;
    double beta;

    mat_df_t ma;

    vec_df_t vx;
    vec_df_t vy;
    vec_df_t vz;

    double buf_st;  /* Single-thread return */
    double buf_mt;  /* Multi-threads return */
    double buf_cf;  /* cblas return */

    struct timespec tp_b;  /* Time of test begin */
    struct timespec tp_e;  /* Time of test end */

    double cst_st;
    double cst_mt;
    double cst_cf;

    printf("gemv() --> cblas_dgemv()\n");
    alpha = random_double();
    beta = -random_double();

    ierr = mat_df_create(PROPER_MATRIX_MAX, PROPER_MATRIX_MIN, &ma);

    ierr = vec_df_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_C_SIZE_RUN, &vx);
    ierr = vec_df_twins_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_R_SIZE_RUN, &vy, &vz);

    /* Row-Major, No Transpose */
    clock_gettime(CLOCK_REALTIME, &tp_b);
    ierr = stblas_gemv(MTBLAS_ROW_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    clock_gettime(CLOCK_REALTIME, &tp_e);
    cst_st = clock_difftime(&tp_b, &tp_e);
    ierr = stblas_nrm2(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_df_twins_reset(&vy, &vz);

    clock_gettime(CLOCK_REALTIME, &tp_b);
    ierr = mtblas_gemv(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    clock_gettime(CLOCK_REALTIME, &tp_e);
    cst_mt = clock_difftime(&tp_b, &tp_e);
    ierr = mtblas_nrm2(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_df_twins_reset(&vy, &vz);

    clock_gettime(CLOCK_REALTIME, &tp_b);
    cblas_dgemv(CblasRowMajor, CblasNoTrans, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    clock_gettime(CLOCK_REALTIME, &tp_e);
    cst_cf = clock_difftime(&tp_b, &tp_e);
    buf_cf = cblas_dnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("ROW_MAJOR, TRANS_NONE:\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    printf("Time Cost: %10.6lf, %10.6lf, %10.6lf\n", cst_st, cst_mt, cst_cf);

    /* Row-Major, Transpose */
    ierr = vec_df_twins_reset(&vy, &vz);

    ierr = stblas_gemv(MTBLAS_ROW_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_df_twins_reset(&vy, &vz);

    ierr = mtblas_gemv(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_df_twins_reset(&vy, &vz);

    cblas_dgemv(CblasRowMajor, CblasTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    buf_cf = cblas_dnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("ROW_MAJOR, TRANS:\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    /* Row-Major, Conjugate Transpose */
    ierr = vec_df_twins_reset(&vy, &vz);

    ierr = stblas_gemv(MTBLAS_ROW_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_df_twins_reset(&vy, &vz);

    ierr = mtblas_gemv(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_df_twins_reset(&vy, &vz);

    cblas_dgemv(CblasRowMajor, CblasConjTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    buf_cf = cblas_dnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("ROW_MAJOR, CONJ TRANS:\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    /* Column-Major, No Transpose */
    ierr = vec_df_twins_reset(&vy, &vz);

    ierr = stblas_gemv(MTBLAS_COL_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_df_twins_reset(&vy, &vz);

    ierr = mtblas_gemv(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_df_twins_reset(&vy, &vz);

    cblas_dgemv(CblasColMajor, CblasNoTrans, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    buf_cf = cblas_dnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("COL_MAJOR, TRANS_NONE:\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    /* Column-Major, Transpose */
    ierr = vec_df_twins_reset(&vy, &vz);

    ierr = stblas_gemv(MTBLAS_COL_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_df_twins_reset(&vy, &vz);

    ierr = mtblas_gemv(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_df_twins_reset(&vy, &vz);

    cblas_dgemv(CblasColMajor, CblasTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    buf_cf = cblas_dnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("COL_MAJOR, TRANS:\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    /* Column-Major, Conjugate Transpose */
    ierr = vec_df_twins_reset(&vy, &vz);

    ierr = stblas_gemv(MTBLAS_COL_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_df_twins_reset(&vy, &vz);

    ierr = mtblas_gemv(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_df_twins_reset(&vy, &vz);

    cblas_dgemv(CblasColMajor, CblasConjTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    buf_cf = cblas_dnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("COL_MAJOR, CONJ TRANS:\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    ierr = vec_df_delete(&vx);
    ierr = vec_df_delete(&vy);
    ierr = vec_df_delete(&vz);

    ierr = mat_df_delete(&ma);

    return ierr;
}


int test_gemvl(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    long double alpha;
    long double beta;

    mat_lf_t ma;

    vec_lf_t vx;
    vec_lf_t vy;
    vec_lf_t vz;

    long double buf_st;  /* Single-thread return */
    long double buf_mt;  /* Multi-threads return */

    printf("gemvl()\n");
    alpha = random_long_double();
    beta = -random_long_double();

    ierr = mat_lf_create(PROPER_MATRIX_MAX, PROPER_MATRIX_MIN, &ma);

    ierr = vec_lf_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_C_SIZE_RUN, &vx);
    ierr = vec_lf_twins_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_R_SIZE_RUN, &vy, &vz);

    /* Row-Major, No Transpose */
    ierr = stblas_gemvl(MTBLAS_ROW_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2l(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_lf_twins_reset(&vy, &vz);

    ierr = mtblas_gemvl(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2l(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    printf("ROW_MAJOR, TRANS_NONE:\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    /* Row-Major, Transpose */
    ierr = vec_lf_twins_reset(&vy, &vz);

    ierr = stblas_gemvl(MTBLAS_ROW_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2l(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_lf_twins_reset(&vy, &vz);

    ierr = mtblas_gemvl(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2l(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    printf("ROW_MAJOR, TRANS:\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    /* Row-Major, Conjugate Transpose */
    ierr = vec_lf_twins_reset(&vy, &vz);

    ierr = stblas_gemvl(MTBLAS_ROW_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2l(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_lf_twins_reset(&vy, &vz);

    ierr = mtblas_gemvl(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2l(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    printf("ROW_MAJOR, CONJ TRANS:\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    /* Column-Major, No Transpose */
    ierr = vec_lf_twins_reset(&vy, &vz);

    ierr = stblas_gemvl(MTBLAS_COL_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2l(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_lf_twins_reset(&vy, &vz);

    ierr = mtblas_gemvl(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2l(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    printf("COL_MAJOR, TRANS_NONE:\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    /* Column-Major, Transpose */
    ierr = vec_lf_twins_reset(&vy, &vz);

    ierr = stblas_gemvl(MTBLAS_COL_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2l(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_lf_twins_reset(&vy, &vz);

    ierr = mtblas_gemvl(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2l(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);
    printf("COL_MAJOR, TRANS:\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    /* Column-Major, Conjugate Transpose */
    ierr = vec_lf_twins_reset(&vy, &vz);

    ierr = stblas_gemvl(MTBLAS_COL_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_nrm2l(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_lf_twins_reset(&vy, &vz);

    ierr = mtblas_gemvl(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_nrm2l(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);
    printf("COL_MAJOR, CONJ TRANS:\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    ierr = vec_lf_delete(&vx);
    ierr = vec_lf_delete(&vy);
    ierr = vec_lf_delete(&vz);

    ierr = mat_lf_delete(&ma);

    return ierr;
}


int test_cgemvf(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    float complex alpha;
    float complex beta;

    mat_fc_t ma;

    vec_fc_t vx;
    vec_fc_t vy;
    vec_fc_t vz;

    float buf_st;  /* Single-thread return */
    float buf_mt;  /* Multi-threads return */
    float buf_cf;  /* cblas return */

    printf("cgemvf() --> cblas_cgemv()\n");
    alpha = random_float() + _Complex_I * random_float();
    beta = -random_float() + _Complex_I * random_float();

    ierr = mat_fc_create(PROPER_MATRIX_MAX, PROPER_MATRIX_MIN, &ma);

    ierr = vec_fc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_C_SIZE_RUN, &vx);
    ierr = vec_fc_twins_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_R_SIZE_RUN, &vy, &vz);

    /* Row-Major, No Transpose */
    ierr = stblas_cgemvf(MTBLAS_ROW_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2f(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_fc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemvf(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2f(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_fc_twins_reset(&vy, &vz);

    cblas_cgemv(CblasRowMajor, CblasNoTrans, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, (void*) &alpha, ma.data, ma.row_size, vx.data, vx.step, (void*) &beta, vz.data, vz.step);
    buf_cf = cblas_scnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("ROW_MAJOR, TRANS_NONE:\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    /* Row-Major, Transpose */
    ierr = vec_fc_twins_reset(&vy, &vz);

    ierr = stblas_cgemvf(MTBLAS_ROW_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2f(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_fc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemvf(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2f(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_fc_twins_reset(&vy, &vz);

    cblas_cgemv(CblasRowMajor, CblasTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, (void*) &alpha, ma.data, ma.row_size, vx.data, vx.step, (void*) &beta, vz.data, vz.step);
    buf_cf = cblas_scnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("ROW_MAJOR, TRANS:\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    /* Row-Major, Conjugate Transpose */
    ierr = vec_fc_twins_reset(&vy, &vz);

    ierr = stblas_cgemvf(MTBLAS_ROW_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2f(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_fc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemvf(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2f(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_fc_twins_reset(&vy, &vz);

    cblas_cgemv(CblasRowMajor, CblasConjTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, (void*) &alpha, ma.data, ma.row_size, vx.data, vx.step, (void*) &beta, vz.data, vz.step);
    buf_cf = cblas_scnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("ROW_MAJOR, CONJ TRANS:\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    /* Column-Major, No Transpose */
    ierr = vec_fc_twins_reset(&vy, &vz);

    ierr = stblas_cgemvf(MTBLAS_COL_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2f(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_fc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemvf(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2f(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_fc_twins_reset(&vy, &vz);

    cblas_cgemv(CblasColMajor, CblasNoTrans, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, (void*) &alpha, ma.data, ma.col_size, vx.data, vx.step, (void*) &beta, vz.data, vz.step);
    buf_cf = cblas_scnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("COL_MAJOR, TRANS_NONE:\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    /* Column-Major, Transpose */
    ierr = vec_fc_twins_reset(&vy, &vz);

    ierr = stblas_cgemvf(MTBLAS_COL_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2f(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_fc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemvf(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2f(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_fc_twins_reset(&vy, &vz);

    cblas_cgemv(CblasColMajor, CblasTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, (void*) &alpha, ma.data, ma.col_size, vx.data, vx.step, (void*) &beta, vz.data, vz.step);
    buf_cf = cblas_scnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("COL_MAJOR, TRANS:\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    /* Column-Major, Conjugate Transpose */
    ierr = vec_fc_twins_reset(&vy, &vz);

    ierr = stblas_cgemvf(MTBLAS_COL_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2f(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_fc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemvf(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2f(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_fc_twins_reset(&vy, &vz);

    cblas_cgemv(CblasColMajor, CblasConjTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, (void*) &alpha, ma.data, ma.col_size, vx.data, vx.step, (void*) &beta, vz.data, vz.step);
    buf_cf = cblas_scnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("COL_MAJOR, CONJ TRANS:\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    ierr = vec_fc_delete(&vx);
    ierr = vec_fc_delete(&vy);
    ierr = vec_fc_delete(&vz);

    ierr = mat_fc_delete(&ma);

    return ierr;
}


int test_cgemv(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    double complex alpha;
    double complex beta;

    mat_dc_t ma;

    vec_dc_t vx;
    vec_dc_t vy;
    vec_dc_t vz;

    double buf_st;  /* Single-thread return */
    double buf_mt;  /* Multi-threads return */
    double buf_cf;  /* cblas return */

    printf("cgemv() --> cblas_cgemv()\n");
    alpha = random_double() + _Complex_I * random_double();
    beta = -random_double() + _Complex_I * random_double();

    ierr = mat_dc_create(PROPER_MATRIX_MAX, PROPER_MATRIX_MIN, &ma);

    ierr = vec_dc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_C_SIZE_RUN, &vx);
    ierr = vec_dc_twins_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_R_SIZE_RUN, &vy, &vz);

    /* Row-Major, No Transpose */
    ierr = stblas_cgemv(MTBLAS_ROW_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_dc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemv(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_dc_twins_reset(&vy, &vz);

    cblas_zgemv(CblasRowMajor, CblasNoTrans, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, (void*) &alpha, ma.data, ma.row_size, vx.data, vx.step, (void*) &beta, vz.data, vz.step);
    buf_cf = cblas_dznrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("ROW_MAJOR, TRANS_NONE:\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    /* Row-Major, Transpose */
    ierr = vec_dc_twins_reset(&vy, &vz);

    ierr = stblas_cgemv(MTBLAS_ROW_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_dc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemv(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_dc_twins_reset(&vy, &vz);

    cblas_zgemv(CblasRowMajor, CblasTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, (void*) &alpha, ma.data, ma.row_size, vx.data, vx.step, (void*) &beta, vz.data, vz.step);
    buf_cf = cblas_dznrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("ROW_MAJOR, TRANS:\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    /* Row-Major, Conjugate Transpose */
    ierr = vec_dc_twins_reset(&vy, &vz);

    ierr = stblas_cgemv(MTBLAS_ROW_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_dc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemv(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_dc_twins_reset(&vy, &vz);

    cblas_zgemv(CblasRowMajor, CblasConjTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, (void*) &alpha, ma.data, ma.row_size, vx.data, vx.step, (void*) &beta, vz.data, vz.step);
    buf_cf = cblas_dznrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("ROW_MAJOR, CONJ TRANS:\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    /* Column-Major, No Transpose */
    ierr = vec_dc_twins_reset(&vy, &vz);

    ierr = stblas_cgemv(MTBLAS_COL_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_dc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemv(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_dc_twins_reset(&vy, &vz);

    cblas_zgemv(CblasColMajor, CblasNoTrans, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, (void*) &alpha, ma.data, ma.col_size, vx.data, vx.step, (void*) &beta, vz.data, vz.step);
    buf_cf = cblas_dznrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("COL_MAJOR, TRANS_NONE:\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    /* Column-Major, Transpose */
    ierr = vec_dc_twins_reset(&vy, &vz);

    ierr = stblas_ccopy(PROPER_R_SIZE_RUN, vy.data, vy.step, vz.data, vz.step);
    ierr = stblas_cgemv(MTBLAS_COL_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_dc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemv(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_dc_twins_reset(&vy, &vz);

    cblas_zgemv(CblasColMajor, CblasTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, (void*) &alpha, ma.data, ma.col_size, vx.data, vx.step, (void*) &beta, vz.data, vz.step);
    buf_cf = cblas_dznrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("COL_MAJOR, TRANS:\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    /* Column-Major, Conjugate Transpose */
    ierr = vec_dc_twins_reset(&vy, &vz);

    ierr = stblas_ccopy(PROPER_R_SIZE_RUN, vy.data, vy.step, vz.data, vz.step);
    ierr = stblas_cgemv(MTBLAS_COL_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_dc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemv(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    ierr = vec_dc_twins_reset(&vy, &vz);

    cblas_zgemv(CblasColMajor, CblasConjTrans, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, (void*) &alpha, ma.data, ma.col_size, vx.data, vx.step, (void*) &beta, vz.data, vz.step);
    buf_cf = cblas_dznrm2(PROPER_R_SIZE_RUN, vz.data, vz.step);

    printf("COL_MAJOR, CONJ TRANS:\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    ierr = vec_dc_delete(&vx);
    ierr = vec_dc_delete(&vy);
    ierr = vec_dc_delete(&vz);

    ierr = mat_dc_delete(&ma);

    return ierr;
}


int test_cgemvl(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    long double complex alpha;
    long double complex beta;

    mat_lc_t ma;

    vec_lc_t vx;
    vec_lc_t vy;
    vec_lc_t vz;

    long double buf_st;  /* Single-thread return */
    long double buf_mt;  /* Multi-threads return */

    printf("cgemv() --> cblas_cgemv()\n");
    alpha = random_long_double() + _Complex_I * random_long_double();
    beta = -random_long_double() + _Complex_I * random_long_double();

    ierr = mat_lc_create(PROPER_MATRIX_MAX, PROPER_MATRIX_MIN, &ma);

    ierr = vec_lc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_C_SIZE_RUN, &vx);
    ierr = vec_lc_twins_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_R_SIZE_RUN, &vy, &vz);

    /* Row-Major, No Transpose */
    ierr = stblas_ccopyl(PROPER_R_SIZE_RUN, vy.data, vy.step, vz.data, vz.step);
    ierr = stblas_cgemvl(MTBLAS_ROW_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2l(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_lc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemvl(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2l(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    printf("ROW_MAJOR, TRANS_NONE:\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    /* Row-Major, Transpose */
    ierr = vec_lc_twins_reset(&vy, &vz);

    ierr = stblas_cgemvl(MTBLAS_ROW_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2l(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_lc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemvl(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2l(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    printf("ROW_MAJOR, TRANS:\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    /* Row-Major, Conjugate Transpose */
    ierr = vec_lc_twins_reset(&vy, &vz);

    ierr = stblas_cgemvl(MTBLAS_ROW_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2l(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_lc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemvl(thrz, MTBLAS_ROW_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.row_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2l(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    printf("ROW_MAJOR, CONJ TRANS:\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    /* Column-Major, No Transpose */
    ierr = vec_lc_twins_reset(&vy, &vz);

    ierr = stblas_cgemvl(MTBLAS_COL_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2l(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_lc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemvl(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS_NONE, PROPER_R_SIZE_RUN, PROPER_C_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2l(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    printf("COL_MAJOR, TRANS_NONE:\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    /* Column-Major, Transpose */
    ierr = vec_lc_twins_reset(&vy, &vz);

    ierr = stblas_cgemvl(MTBLAS_COL_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2l(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_lc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemvl(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2l(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    printf("COL_MAJOR, TRANS:\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    /* Column-Major, Conjugate Transpose */
    ierr = vec_lc_twins_reset(&vy, &vz);

    ierr = stblas_cgemvl(MTBLAS_COL_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = stblas_cnrm2l(PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_st);

    ierr = vec_lc_twins_reset(&vy, &vz);

    ierr = mtblas_cgemvl(thrz, MTBLAS_COL_MAJOR, MTBLAS_TRANS_CONJ, PROPER_C_SIZE_RUN, PROPER_R_SIZE_RUN, alpha, ma.data, ma.col_size, vx.data, vx.step, beta, vz.data, vz.step);
    ierr = mtblas_cnrm2l(thrz, PROPER_R_SIZE_RUN, vz.data, vz.step, &buf_mt);

    printf("COL_MAJOR, CONJ TRANS:\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    ierr = vec_lc_delete(&vx);
    ierr = vec_lc_delete(&vy);
    ierr = vec_lc_delete(&vz);

    ierr = mat_lc_delete(&ma);

    return ierr;
}
